-- ArtStatueM
-- Create by panyl
-- 艺术雕像

module("ArtStatueM", package.seeall);

-- 所有的道具信息
local art_statue = {};

local rules = {};

local startDungeon;
local whenLeaveDungeon;

-- 载入配置表
local _init = false;
local loadCsv = function()
    if _init then return end
    _init = true;

    -- 转换下item信息表
    local art_statue_CSV = get_art_statue_CSV();
    for i = 1, #art_statue_CSV do
        art_statue[art_statue_CSV[i].id] = art_statue_CSV[i];
    end

    art_statue_CSV = {};
end

-- 模块初始化
function init()
    if not _init then
        loadCsv();

        -- 载入所有的规则处理子模块
        rules = LOAD_PATH("game/logic/module/art_statue");
    end

    DungeonServiceM.registerStartDungeonCB("art_statue", startDungeon);

    EventMgr.removeAll("ArtStatueM");

    -- 关注离开地牢事件
    EventMgr.register("ArtStatueM", event.LEAVE_DUNGEON, whenLeaveDungeon);
end

-- 检索
function query(id, path)
    local m = art_statue[id];

    if not m or not path then
        return m;
    end

    return m[path];
end

whenLeaveDungeon = function()
    ME.user.dbase:delete("art_statue");
end

startDungeon = function()
    -- 最后一层不能释放
    local dungeonId = DungeonM.getDungeonId();
    local layer = DungeonM.currentLayer();

    -- 副本中不能使用
    if DungeonInstanceM.isInInstance() then
        return false;
    end

    -- boss层不能使用
    if DungeonBossM.isBossLayer(dungeonId, layer) then
        return false;
    end

    -- 夹层迷宫
    if UnrealDungeonM.isInUnreal() then
        return false;
    end

    create_statue();
end

-- 奖励
function calc_statue_bonus(statue_id, seed)
    local bonus = query(statue_id, "bonus");
    if type(bonus) == "table" then
        return bonus;
    end

    if type(bonus) ~= "string" or sizeof(bonus) <= 0 then
        return {};
    end

    -- 公式算
    return FormulaM.invoke(bonus, statue_id, seed);
end

function can_select(index, classId, ignore_exist)
    -- 没有道具了
    if ItemM.getAmount(ME.user, classId) <= 0 then
        return false;
    end

    local args = PropertyM.query(classId, "args") or {};
    if not args["statue_list"] or sizeof(args["statue_list"]) < index then
        return false;
    end

    -- 专属的属性
    local prop = PropM.combine(ME.user, "skill_level", "art_statue");
    if prop[3] < index then
        return false;
    end

    -- 如果场上已经存在雕像
    local para = ME.user.dbase:query("art_statue");
    if not ignore_exist and sizeof(para) > 0 then
        local statue_id = para["statue"];

        return string.format(getLocStr("art_statue_still_exist"), query(statue_id, "name"));
    end

    return true;
end

-- 初始化雕像
function use_art_manuscript(index, class_id)
    if true ~= can_select(index, class_id) then
        return false;
    end

    -- 先扣除道具
    PropertyM.costProperty(ME.user, class_id);

    local args = PropertyM.query(class_id, "args");
    local statue_list = args["statue_list"];

    -- 初始化数据
    local para = {
        ["statue"] = statue_list[index],
        ["seed"]   = DungeonM.getRandSeed("art_manuscript"),
        ["times"]  = 0,
    };
    ME.user.dbase:set("art_statue", para);

    create_statue();

    return true;
end

-- 创建雕像
function create_statue()
    local para = ME.user.dbase:query("art_statue");
    if sizeof(para) <= 0 then
        return false;
    end

    local pos;
    if para["position"] then
        pos = para["position"] + 1;
    end

    -- 用召唤兽的模块找位置
    pos = SummonM.findSummonPos(pos, true);
    if pos <= 0 then
        trace("ArtStatueM", "找不到有效的位置");

        return false;
    end

    local statue_id = para["statue"];
    local dbase = query(statue_id, "dbase");
    local element = dbase["element"];
    local class = DungeonM.queryElement(element, "class");

    trace("ArtStatueM", "%d 雕像坐落在 %d", statue_id, pos);

    -- 找出雕像
    local info = {
        ["class"] = class,
        ["type"]  = DungeonM.query(class, "type"),
        ["pos"]   = pos,
        ["element"] = element,
        ["layer"] = DungeonM.currentLayer(),
    };

    local info = table.add(info, para);

    para["position"] = pos - 1;

    -- 转换格子
    DungeonM.transformGrid(class, pos, GRID_STATE_OPEN, info);

    return true;
end

-- 计算最大次数
function calc_max_engrave(statue_id)
    local max_times = query(statue_id, "max_times");
    local prop = PropM.combine(ME.user, "skill_level", "art_statue_degree");
    max_times = max_times - prop[3];

    return max_times;
end

-- 能否雕刻
function can_carving_statue(pos)
    local grid = DungeonM.getGridByPos(pos);

    if GRID_TYPE_ART_STATUE ~= grid.type then
        return false;
    end

    if GRID_STATE_DISABLE == grid.state then
        return false;
    end

    local para = ME.user.dbase:query("art_statue");

    -- 如果本层已经雕刻过一次了
    local layer = DungeonM.currentLayer();
    if layer == para["over_layer"] then
        return "duplicate_carving";
    end

    -- 消耗
    local statue_id = grid.statue;
    local cost = query(statue_id, "require") or {};
    for attrib, value in pairs(cost) do
        if ME.user:queryAttrib(attrib) < value then
            return string.format(getLocStr("lack_bullet"), FieldsM.getFieldName(attrib));
        end
    end

    return true;
end

-- 完成一次雕刻
function carving_statue(pos)
    if true ~= can_carving_statue(pos) then
        return false;
    end

    local grid = DungeonM.getGridByPos(pos);
    local para = ME.user.dbase:query("art_statue");

    local times = tonumber(grid.times);
    local statue_id = grid.statue;


    -- 雕像已经完成了
    if times >= calc_max_engrave(statue_id) then
        return false;
    end

    -- 消耗
    local cost = query(statue_id, "require") or {};
    for attrib, value in pairs(cost) do
        ME.user:costAttrib(attrib, value);
    end

    -- 设置次数
    para["times"] = tonumber(para["times"]) + 1;
    para["over_layer"] = DungeonM.currentLayer();

    grid.times = times + 1;

    return true;
end

-- 是否已经完成了
function is_completed(pos)
    local grid = DungeonM.getGridByPos(pos);

    if GRID_TYPE_ART_STATUE ~= grid.type then
        return false;
    end

    if GRID_STATE_DISABLE == grid.state then
        return false;
    end

    local times = tonumber(grid.times);
    local statue_id = grid.statue;

    -- 雕像还未完成
    return times >= calc_max_engrave(statue_id);
end

-- 领取奖励
function take_bonus(pos)
    local grid = DungeonM.getGridByPos(pos);

    if GRID_TYPE_ART_STATUE ~= grid.type then
        return false;
    end

    if GRID_STATE_DISABLE == grid.state then
        return false;
    end

    local times = tonumber(grid.times);
    local statue_id = grid.statue;

    -- 雕像还未完成
    if times < calc_max_engrave(statue_id) then
        return false;
    end

    -- 计算奖励
    local para = ME.user.dbase:query("art_statue");
    local seed = para["seed"];

    local tips = getLocStr("art_statue_bonus_tip") .. get_bonus_desc();

    -- 清除数据
    ME.user.dbase:delete("art_statue");

    -- 格子设置为不可用
    grid:changeState(GRID_STATE_DISABLE);

    -- 奖励
    local m = calc_statue_bonus(statue_id, seed);
    for key, bonus in pairs(m) do
        if "prop" == key or "limit_prop" == key then
            -- 属性奖励
            -- 多个属性
            for _, prop in pairs(bonus) do
                PropM.record(ME.user, prop, "art_statue");
            end

            if "limit_prop" == key then
                CombatStatM.addFieldStat("art_statue_limit", 1);
            end
        elseif "bonus" == key then
            for _, arr in pairs(bonus) do
                BonusM.doBonus(arr);
            end
        end
    end

    -- 抛出通用建筑奖励事件
    EventMgr.fire(event.COMM_BUILDING_BONUS, {
        ["pos"]   = pos,
        ["type"]  = grid.type,
        ["bonus"] = { ["bonus"] = m["bonus"] or {}, },
        ["remainGrid"] = false,
        ["tips"] = tips,
    });

    return true;
end

-- 获取奖励描述
function get_bonus_desc()
    local para = ME.user.dbase:query("art_statue");
    if sizeof(para) <= 0 then
        return "";
    end

    local m = calc_statue_bonus(para["statue"], para["seed"]);

    local desc = "";

    local bonus = m["bonus"] or {};
    for _, arr in pairs(bonus) do
        local attrib = arr[2];
        local value  = arr[3];
        if 2 == arr[1] then
            desc = desc .. string.format(getLocStr("gumball_attrib_bonus_format"), FieldsM.getFieldName(attrib), value) .. "\n";
        end
    end

    -- 属性的
    local props = m["limit_prop"] or {};
    for _, prop in pairs(props) do
        desc = desc .. PropM.getPropDesc(prop) .. "\n";
    end

    props = m["prop"] or {};
    for _, prop in pairs(props) do
        desc = desc .. PropM.getPropDesc(prop) .. "\n";
    end

    -- 抽取掉颜色等信息
    -- desc = extractString(desc);

    return desc;
end
